package com.newidea.jiangong.service.impi;

import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.newidea.jiangong.entity.HeatFacility;
import com.newidea.jiangong.mapper.HeatFacilityMapper;
import com.newidea.jiangong.service.HeatFacilityService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.Transient;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
@Slf4j
public class HeatFacilityServiceImpl extends ServiceImpl<HeatFacilityMapper, HeatFacility>
        implements HeatFacilityService {

    private final HeatFacilityMapper heatFacilityMapper;

    public HeatFacilityServiceImpl(HeatFacilityMapper heatFacilityMapper) {
        this.heatFacilityMapper = heatFacilityMapper;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void analysis(JSONObject jsonObject, String company) {
        // 以前数据设置为旧数据
        HeatFacility updateEntity = new HeatFacility();
        updateEntity.setNewest(false);

        QueryWrapper<HeatFacility> updateWrapper = new QueryWrapper<>();
        // 是否获取最新的数据
        updateWrapper.eq("company", company);
        this.update(updateEntity, updateWrapper);

        // 获取状态数据
        JSONArray states = jsonObject.getJSONArray("states");
        List<HeatFacility> stateList = states.toList(HeatFacility.class).stream()
                .peek(state -> {
                    state.setNewest(true);
                    state.setCompany(company);
                }).collect(Collectors.toList());
        // 保存状态数据
        this.saveBatch(stateList);

        // 获取锅炉和变热器数据
        JSONArray values = jsonObject.getJSONArray("values");

        List<HeatFacility> valueList = values.toList(HeatFacility.class);
        for (HeatFacility heatFacility : valueList) {
            // Modbus通信获取的值
            String value = heatFacility.getValue();
            String[] split = value.split(",");
            // 2个数为一个有效值
            if (split.length == 2) {
                // 将Modbus通信获取的值转换位可读值
                heatFacility.setValue(getResult(split[0], split[1]));
            } else {
                heatFacility.setValue(split[0]);
            }
            heatFacility.setCompany(company);
            heatFacility.setNewest(true);
        }
        // 保存锅炉和变热器数据
        this.saveBatch(valueList);
    }


    /**
     * 采集华威的锅炉数据
     *
     * @param jsonArray 锅炉数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void hwGlSave(JSONArray jsonArray) {
        String company = "华威";
        // 以前数据设置为旧数据
        HeatFacility updateEntity = new HeatFacility();
        updateEntity.setNewest(false);

        // 指定公司
        QueryWrapper<HeatFacility> updateWrapper = new QueryWrapper<>();
        updateWrapper.eq("company", company);
        this.update(updateEntity, updateWrapper);

        // 定义格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 当前时间就是采集时间
        String createTime = LocalDateTime.now().format(formatter);

        InputStream in = this.getClass().getClassLoader().getResourceAsStream("huawei/hwGl.json");
        if (in == null) {
            throw new RuntimeException("未能读取到配置文件facilityState.json");
        }
        JSONObject entries = JSONUtil.parseObj(IoUtil.read(in, StandardCharsets.UTF_8));

        List<HeatFacility> saveList = new ArrayList<>();
        // 保存锅炉数据
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject json = jsonArray.getJSONObject(i);

            HeatFacility heatFacility = new HeatFacility();
            // 设备地址
            String modbusID = json.getStr("modbusID");
            heatFacility.setAddress(modbusID);
            // 设备名称
            heatFacility.setName(entries.getStr(modbusID));
            // 值
            heatFacility.setValue(json.getStr("currValue"));
            heatFacility.setCompany(company);
            heatFacility.setNewest(true);
            heatFacility.setCreateTime(createTime);
            saveList.add(heatFacility);
        }
        // 保存锅炉和变热器数据
        this.saveBatch(saveList);
    }


    /**
     * 将Modbus通信获取的值转换位可读值
     *
     * @param high 高端值
     * @param low  低端值
     * @return 可读值
     */
    private String getResult(String high, String low) {
        // 创建一个ByteBuffer，并按照字节顺序（大端或小端）将两个16位整数放入其中
        ByteBuffer buffer = ByteBuffer.allocate(4);
        // 获取到的负数会转为无符号，需要重新转换回来
        buffer.putShort(Integer.valueOf(high).shortValue());
        buffer.putShort(Integer.valueOf(low).shortValue());

        // 切换为读取模式
        buffer.flip();

        // 读取合并后的浮点数
        return String.format("%.2f", buffer.getFloat());
    }


    /**
     * 获取设备地址对应的值
     *
     * @param company 所属公司
     * @return map设备地址对应的值
     */
    @Override
    public Map<String, String> getFacilityMap(String company) {
        // 查询大屯Modbus数据
        QueryWrapper<HeatFacility> wrapper = new QueryWrapper<>();
        wrapper.select("address", "value", "create_time")
                // 是否获取最新的数据
                .eq("newest", true)
                .eq("company", company);
        List<HeatFacility> list = heatFacilityMapper.selectList(wrapper);

        if (list.isEmpty()) {
            return new HashMap<>();
        }
        // 转化为地址 ：value
        Map<String, String> facilityMap = list.stream().collect(
                Collectors.toMap(HeatFacility::getAddress, HeatFacility::getValue)
        );
        facilityMap.put("create_time", list.get(0).getCreateTime());
        return facilityMap;
    }
}
